import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.swing.border.*;
import javax.swing.filechooser.*;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.io.FileOutputStream;
import java.awt.Image;
import java.awt.image.*;
import javax.imageio.*;
import java.awt.Color;
import java.util.Arrays;
import java.lang.*;
import java.awt.Graphics;
import java.util.*;
import java.math.*;
import com.xuggle.mediatool.IMediaReader;
import com.xuggle.mediatool.MediaListenerAdapter;
import com.xuggle.mediatool.ToolFactory;
import com.xuggle.mediatool.event.IVideoPictureEvent;
import com.xuggle.xuggler.Global;

/**
 * Created with IntelliJ IDEA.
 * User: root
 * Date: 11/6/12
 * Time: 10:44 AM
 * To change this template use File | Settings | File Templates.
 */
public class VideoThumbnailsExample {
    public static final double SECONDS_BETWEEN_FRAMES = 1;
    private static final String inputFilename = "/root/Desktop/TA/video2/MOV03645.MPG";
    private static final String outputFilePrefix = "/root/Desktop/snapshot1/";

    // The video stream index, used to ensure we display frames from one and
    // only one video stream from the media container.
    private static int mVideoStreamIndex = -1;

    // Time of last frame write
    private static long mLastPtsWrite = Global.NO_PTS;

    public static final long MICRO_SECONDS_BETWEEN_FRAMES =
            (long)(Global.DEFAULT_PTS_PER_SECOND * SECONDS_BETWEEN_FRAMES);

    public static void main(String[] args) {

        IMediaReader mediaReader = ToolFactory.makeReader(inputFilename);

        // stipulate that we want BufferedImages created in BGR 24bit color space
        mediaReader.setBufferedImageTypeToGenerate(BufferedImage.TYPE_3BYTE_BGR);

        mediaReader.addListener(new ImageSnapListener());

        // read out the contents of the media file and
        // dispatch events to the attached listener
        while (mediaReader.readPacket() == null) ;

    }

    private static class Node
    {
        int w;
        Node[] child; //declaration child node
        double value;
        Node left,right; //declaration left and right child node
        double scale,realHeight;

        public Node(double value){
            this.value = value; //get input value
        }

        public void initChild(){
            child = new Node[w]; //inisialization child Node
        }

        public Node(double scale, double realHeight){
            this.scale = scale; //get input scale value
            this.realHeight = realHeight; //get input realHeight value
        }
    }

    private static class ImageSnapListener extends MediaListenerAdapter {

        public void onVideoPicture(IVideoPictureEvent event) {

            if (event.getStreamIndex() != mVideoStreamIndex) {
                // if the selected video stream id is not yet set, go ahead an
                // select this lucky video stream
                if (mVideoStreamIndex == -1)
                    mVideoStreamIndex = event.getStreamIndex();
                    // no need to show frames from this video stream
                else
                    return;
            }

            // if uninitialized, back date mLastPtsWrite to get the very first frame
            if (mLastPtsWrite == Global.NO_PTS)
                mLastPtsWrite = event.getTimeStamp() - MICRO_SECONDS_BETWEEN_FRAMES;

            // if it's time to write the next frame
            if (event.getTimeStamp() - mLastPtsWrite >= MICRO_SECONDS_BETWEEN_FRAMES)
            {

                String outputFilename = dumpImageToFile(event.getImage());

                // indicate file written
                double seconds = ((double) event.getTimeStamp()) / Global.DEFAULT_PTS_PER_SECOND;
                System.out.printf("at elapsed time of %6.3f seconds wrote: %s\n",seconds, outputFilename);

                // update last write time
                mLastPtsWrite += MICRO_SECONDS_BETWEEN_FRAMES;
            }

        }

        private String dumpImageToFile(BufferedImage image) {
            try {
                String outputFilename = outputFilePrefix +
                        System.currentTimeMillis() + ".png";
                ImageIO.write(image, "png", new File(outputFilename));

                File fileGambar = new File(outputFilename);
                BufferedImage image1 = ImageIO.read(fileGambar); //read File fileGambar

                int x = 0; int y = 0; int w,h;
                w = image1.getWidth(); //get the width of selected image
                h = image1.getHeight(); //get the height of selected image
                double Sx, Sy;
                BufferedImage gambar = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_GRAY); //make Buffered image for grayscale image
                WritableRaster raster = gambar.getRaster(); //raster to give pixel value

                BufferedImage gambarTepi = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_GRAY); //make Buffered image for edge detection image
                WritableRaster rasterTepi = gambarTepi.getRaster(); //raster to give pixel value

                /*Grayscale Process*/
                int clr = image1.getRGB(0, 0); //get RGB value of image
                int red = (clr & 0x00ff0000) >> 16; //get Red value of image
                int green = (clr & 0x0000ff00) >> 8; //get Green value of image
                int blue = clr & 0x000000ff; //get Blue value of image
                double gray = (0.3 * red + 0.59 * green + 0.11 * blue); //calculation to get Gray value
                Node rootnode = new Node(gray); //declaration and inisialization Node class and to make first node(root/parent) with gray value in pixel(0,0)
                rootnode.initChild(); //call initChild method with the name of root/parent is rootnode

                for (y = 0; y < h; y++) //level 2 of tree
                {
                    clr = image1.getRGB(0, y);
                    red = (clr & 0x00ff0000) >> 16;
                    green = (clr & 0x0000ff00) >> 8;
                    blue = clr & 0x000000ff;
                    gray = (0.3 * red + 0.59 * green + 0.11 * blue);
                    Node child = new Node(gray); //declaration and inisialization child of rootnode with gray value in pixel(0,y)
                    child.initChild();
                    rootnode.child[y] = child; //put new child with rootnode as parent
                    raster.setSample(x, y, 0, gray);
                }
                for (y = 0; y < h; y++) //level 3 of tree
                {
                    for (x = 1; x < w; x++)
                    {
                        clr = image1.getRGB(x, y);
                        red = (clr & 0x00ff0000) >> 16;
                        green = (clr & 0x0000ff00) >> 8;
                        blue = clr & 0x000000ff;
                        gray = (0.3 * red + 0.59 * green + 0.11 * blue);
                        Node child = new Node(gray);
                        Node parent = rootnode.child[y]; //make new parent to put new child
                        parent.child[x] = child; //put new child with the name of new parent is parent
                        raster.setSample(x, y, 0, gray);
                    }
                }
                ImageIO.write(gambar,"JPG",new File("Gray.jpg"));
                for(x=0;x<w-2;x++)
                {
                    for(y=0;y<h-2;y++)
                    {
                        if(x==0)
                        {
                            Node parent1 = rootnode.child[y];
                            Node parent2 = rootnode.child[y+1];
                            Node parent3 = rootnode.child[y+2];
                            Sx=(-1*rootnode.child[y].value)+(-2*rootnode.child[y+1].value)+(-1*rootnode.child[y+2].value)+parent1.child[2].value+(2*parent2.child[2].value)+parent3.child[2].value; /*calculation edge detection value with matrix mask |-1 0 1|
																					   |-2 0 2|
																					   |-1 0 1|*/

                            Sy=rootnode.child[y].value+(2*parent1.child[1].value)+parent1.child[2].value+(-1*rootnode.child[y+2].value)+(-2*parent3.child[1].value)+(-1*parent3.child[2].value); /*calculation edge detection value with matrix mask | 1  2  1|
																					 | 0  0  0|
																					 |-1 -2 -1|*/
                        }
                        else
                        {
                            Node kepala1 = rootnode.child[y];
                            Node kepala2 = rootnode.child[y+1];
                            Node kepala3 = rootnode.child[y+2];
                            Sx=(-1*kepala1.child[x].value)+(-2*kepala2.child[x].value)+(-1*kepala3.child[x].value)+kepala1.child[x+2].value+(2*kepala2.child[x+2].value)+kepala3.child[x+2].value; /*calculation edge detection value with matrix mask |-1 0 1|
																					   |-2 0 2|
																					   |-1 0 1|*/

                            Sy=kepala1.child[x].value+(2*kepala1.child[x+1].value)+kepala1.child[x+2].value+(-1*kepala3.child[x].value)+(-2*kepala3.child[x+1].value)+(-1*kepala3.child[x+2].value); /*calculation edge detection value with matrix mask | 1  2  1|
																					   | 0  0  0|
																					   |-1 -2 -1|*/
                        }

                        /*make Sx and Sy value to positive*/
                        if(Sx<0 && Sy<0)
                        {
                            Sx=-1*Sx;
                            Sy=-1*Sy;
                        }
                        else if(Sx<0 && Sy>0) Sx=-1*Sx;
                        else if(Sx>0 && Sy<0) Sy=-1*Sy;
                        else
                        {
                            Sx=1*Sx;
                            Sy=1*Sy;
                        }
                        rasterTepi.setSample(x, y, 0, (Sx+Sy));
                    }
                }
                ImageIO.write(gambarTepi,"JPG",new File("Tepi.jpg")); //Saving image use JPG format with the name is Tepi.jpg

                return outputFilename;
            }
            catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }

    }
}

